package com.itheima.d9_KuoZhang2;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName MyRunnable
 * @Author 16799
 * @Date 2025/8/30 21:25
 * @Version 1.0
 * @Description TODO
 **/
    /*  不加锁时：
玛德磊哥视频自己100个线程累加count到9999，没到一万，视频弹幕也有人说其他数字，也有人和我一样都到了一万
磊哥：假设某次count加到了10，这时假设有a线程把count加一，同时b线程来访问count也加一，所以再写进去的话count都是11，就丢了一次线程的count++
简单的说就是 ++count，这个操作出现了线程安全问题，不是原子性的操作
所以要加锁
 */

    /*  加锁之后：
    给for循环加悲观锁之后：但是至于是哪一个线程加的count是不一定的，并不是说线程1加了一百次count后线性的轮到线程2加一百次count
    弹幕：有问题的朋友是太理想化了，真正程序跑起来，他不一定就完全是线性的，可能代码执行一半，时间片丢失，就下一个线程了
    弹幕：Thread通过start方法去启动了target这个任务，然后target会自动调run方法，所以run里的this是target
     */

    /*
    不加锁时，出现冲突的概率很低，所以有人提出了不加锁，而是在每次拿count修改之前，这个线程都会先记录原始的count版本值是多少，
     接着线程再把count改成11，然后把这个11往里面修改的时候，会先比较一下里面的count值是不是自己之前记录的原始count值，
     如果还是10，那就是没有被其他的线程改过，可以放心的往里面修改新的count值。如果不同的话，就是在该线程修改之前，
     有其他的线程修改过了count值，所以该线程把这次的修改作废，然后拿被修改的count值11重复这个修改过程
        这就是乐观锁的机制，只解决这种冲突，由于并不需要加锁并且大多数情况下都不会冲突，所以性能很高
    Java内置了很多乐观锁的技术，比如整数修改的乐观锁：原子类实现的
     */
public class MyRunnable implements Runnable{
/*    //统计浏览人数
    public static int count;*/

    //整数修改的乐观锁：原子类实现的，可以把上面那种形式给替换掉
    private AtomicInteger count = new AtomicInteger();  //保证线程安全，这个里面就是乐观锁实现的

    @Override
    public void run() {

/*
        //不加锁时：
        for (int i = 0; i < 100; i++) {
            System.out.println("线程名字："+Thread.currentThread().getName()+"浏览人数总数count为： "+(++count));
        }
        */

/*
        //加锁之后，因为this是指这个MyRunnable的实例对象，且我们只创建了一个MyRunnable实例对象
        for (int i = 0; i < 100; i++) {
            //这是一个悲观锁，因为每一个线程执行++count的时候都要排队，也就是说每一个线程都要跑一百次所以都要排队一百次，一百个线程就要排队一万次，所以悲观锁性能很差
            synchronized (this) {
                System.out.println("线程名字：" + Thread.currentThread().getName() + "浏览人数总数count为： " + (++count));
            }
        }
        */
        for (int i = 0; i < 100; i++) {
            //System.out.println("线程名字："+Thread.currentThread().getName()+"浏览人数总数count为： "+(++count));

            //用原子类实现的count调用incrementAndGet方法，翻译一下就是把底层值加一再取出来展示，所以就相当于++
            //后续讲解incrementAndGet的源码是否是乐观锁，没听懂
            System.out.println("线程名字："+Thread.currentThread().getName()+"浏览人数总数count为： "+(count.incrementAndGet()));

        }

    }
}
